Handle has_alpha_background for parent-relative backgrounds
authorAlexander Larsson <alexl@redhat.com>
Mon, 5 Dec 2011 09:55:55 +0000 (10:55 +0100)
committerAlexander Larsson <alexl@redhat.com>
Mon, 5 Dec 2011 09:55:55 +0000 (10:55 +0100)
gdk/gdkwindow.c

index 04026ac4144eb09ea42ba880dc5e0a47c5acaccb..4c669b51b4e6e81e88829933d3795f0c4c6363d9 100644 (file)
@@ -255,6 +255,7 @@ static void gdk_window_invalidate_rect_full (GdkWindow          *window,
                                             const GdkRectangle *rect,
                                             gboolean            invalidate_children,
                                             ClearBg             clear_bg);
+static void _gdk_window_propagate_has_alpha_background (GdkWindow *window);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -1637,10 +1638,22 @@ gdk_window_reparent (GdkWindow *window,
 
   _gdk_window_update_viewable (window);
 
+  if (window->background == NULL)
+    {
+      /* parent relative background, update has_alpha_background */
+      if (window->parent == NULL ||
+         window->parent->window_type == GDK_WINDOW_ROOT)
+       window->has_alpha_background = FALSE;
+      else
+       window->has_alpha_background = window->parent->has_alpha_background;
+    }
+
   recompute_visible_regions (window, TRUE, FALSE);
   if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
     recompute_visible_regions (old_parent, FALSE, TRUE);
 
+  _gdk_window_propagate_has_alpha_background (window);
+
   /* We used to apply the clip as the shape, but no more.
      Reset this to the real shape */
   if (gdk_window_has_impl (window) &&
@@ -6491,6 +6504,29 @@ gdk_window_set_background_rgba (GdkWindow *window,
   cairo_pattern_destroy (pattern);
 }
 
+
+/* Updates has_alpha_background recursively for all child windows
+   that have parent-relative alpha */
+static void
+_gdk_window_propagate_has_alpha_background (GdkWindow *window)
+{
+  GdkWindow *child;
+  GList *l;
+
+  for (l = window->children; l; l = l->next)
+    {
+      child = l->data;
+
+      if (child->background == NULL &&
+         child->has_alpha_background != window->has_alpha_background)
+       {
+         child->has_alpha_background = window->has_alpha_background;
+         recompute_visible_regions (child, TRUE, FALSE);
+         _gdk_window_propagate_has_alpha_background (child);
+       }
+    }
+}
+
 /**
  * gdk_window_set_background_pattern:
  * @window: a #GdkWindow
@@ -6523,53 +6559,68 @@ gdk_window_set_background_pattern (GdkWindow *window,
   window->background = pattern;
 
   has_alpha = TRUE;
-  type = cairo_pattern_get_type (pattern);
-  
-  if (type == CAIRO_PATTERN_TYPE_SOLID)
+
+  if (pattern == NULL)
     {
-      double alpha;
-      cairo_pattern_get_rgba (pattern, NULL, NULL, NULL, &alpha);
-      if (alpha == 1.0)
+      /* parent-relative, copy has_alpha from parent */
+      if (window->parent == NULL ||
+         window->parent->window_type == GDK_WINDOW_ROOT)
        has_alpha = FALSE;
+      else
+       has_alpha = window->parent->has_alpha_background;
     }
-  else if (type == CAIRO_PATTERN_TYPE_LINEAR ||
-          type == CAIRO_PATTERN_TYPE_RADIAL)
+  else
     {
-      int i, n;
-      double alpha;
+      type = cairo_pattern_get_type (pattern);
 
-      n = 0;
-      cairo_pattern_get_color_stop_count (pattern, &n);
-      has_alpha = FALSE;
-      for (i = 0; i < n; i++)
+      if (type == CAIRO_PATTERN_TYPE_SOLID)
        {
-         cairo_pattern_get_color_stop_rgba (pattern, i, NULL,
-                                            NULL, NULL, NULL, &alpha);
-         if (alpha != 1.0)
+         double alpha;
+         cairo_pattern_get_rgba (pattern, NULL, NULL, NULL, &alpha);
+         if (alpha == 1.0)
+           has_alpha = FALSE;
+       }
+      else if (type == CAIRO_PATTERN_TYPE_LINEAR ||
+              type == CAIRO_PATTERN_TYPE_RADIAL)
+       {
+         int i, n;
+         double alpha;
+
+         n = 0;
+         cairo_pattern_get_color_stop_count (pattern, &n);
+         has_alpha = FALSE;
+         for (i = 0; i < n; i++)
            {
-             has_alpha = TRUE;
-             break;
+             cairo_pattern_get_color_stop_rgba (pattern, i, NULL,
+                                                NULL, NULL, NULL, &alpha);
+             if (alpha != 1.0)
+               {
+                 has_alpha = TRUE;
+                 break;
+               }
            }
        }
+      else if (type == CAIRO_PATTERN_TYPE_SURFACE)
+       {
+         cairo_surface_t *surface;
+         cairo_content_t content;
+
+         cairo_pattern_get_surface (pattern, &surface);
+         content = cairo_surface_get_content (surface);
+         has_alpha =
+           (content == CAIRO_CONTENT_ALPHA) ||
+           (content == CAIRO_CONTENT_COLOR_ALPHA);
+       }
     }
-  else if (type == CAIRO_PATTERN_TYPE_SURFACE)
-    {
-      cairo_surface_t *surface;
-      cairo_content_t content;
 
-      cairo_pattern_get_surface (pattern, &surface);
-      content = cairo_surface_get_content (surface);
-      has_alpha =
-       (content == CAIRO_CONTENT_ALPHA) ||
-       (content == CAIRO_CONTENT_COLOR_ALPHA);
-    }
-  
   if (has_alpha != window->has_alpha_background)
     {
       window->has_alpha_background = has_alpha;  
       recompute_visible_regions (window, TRUE, FALSE);
+
+      _gdk_window_propagate_has_alpha_background (window);
     }
-  
+
   if (gdk_window_has_impl (window))
     {
       GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);